package com.xiaobing.common.aspectj;

import com.xiaobing.common.annotation.UserOptLogger;
import com.xiaobing.common.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author :rui
 * @DESCRIPTION : UserOptLogger切面类
 */
@Aspect
@Component
@Slf4j
public class UserOptLoggerAspect {

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.xiaobing.common.annotation.UserOptLogger)")
    public void entryPoint() {
    }


    /**
     * 非异常 走环绕通知  出现直接记录参数等日志信息
     *
     * @param point
     * @throws Throwable
     */
    @Around("entryPoint()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object result = point.proceed(  );
        try {
            toAbnormalInfo(point, null );
        } catch (Exception e) {
            log.error("日志记录异常", e);
        }
        return result;
    }


    /**
     * around日志记录
     *
     * @ param  point
     * @throws SecurityException
     * @throws NoSuchMethodException
     */
//    public void handleAround(ProceedingJoinPoint point) throws Exception {
//        Signature sig = point.getSignature();
//        MethodSignature msig = null;
//        if (!(sig instanceof MethodSignature)) {
//            throw new IllegalArgumentException("该注解只能用于方法");
//        }
//        msig = (MethodSignature) sig;
//        Object target = point.getTarget();
//        Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
//        // 方法名称
//        String methodName = currentMethod.getName();
//        // 获取注解对象
//        UserOptLogger aLog = currentMethod.getAnnotation(UserOptLogger.class);
//        // 类名
//        String className = point.getTarget().getClass().getName();
//        // 方法的参数
//        Object[] params = point.getArgs();
//
//        StringBuilder paramsBuf = new StringBuilder();
//        for (Object arg : params) {
//            paramsBuf.append(arg);
//            paramsBuf.append("&");
//        }
//        InetAddress localHost = InetAddress.getLocalHost();
//        String ipAddress = localHost.getHostAddress();
//        // *========控制台输出=========*//
//        log.info("用户IP：{} 执行了,类:{},方法名：{},参数:{}", ipAddress, className, methodName, paramsBuf);
//    }

    /**
     *  异常通知走此逻辑  出现异常时记录日志
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "entryPoint()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        toAbnormalInfo(joinPoint, e);
//        Object[] args = joinPoint.getArgs();
//        try {
//            String targetName = joinPoint.getTarget().getClass().getName();
//            String className = joinPoint.getTarget().getClass().getName();
//            String methodName = joinPoint.getSignature().getName();
//            Object[] arguments = joinPoint.getArgs();
//            Class<?> targetClass = Class.forName(targetName);
//            Method[] methods = targetClass.getMethods();
//            String operation = "";
//            for (Method method : methods) {
//                if (method.getName().equals(methodName)) {
//                    Class<?>[] clazzs = method.getParameterTypes();
//                    if (clazzs.length == arguments.length) {
//                        operation = method.getAnnotation(UserOptLogger.class).operation();
//                        break;
//                    }
//                }
//            }
//
//            StringBuilder paramsBuf = new StringBuilder();
//            for (Object arg : arguments) {
//                paramsBuf.append(arg);
//                paramsBuf.append("&");
//            }
//            // *========控制台输出=========*//
//            log.info("异常方法:{}.{};参数：{}", className, methodName, paramsBuf);
//
//            String ipAddress = IpUtil.getIpAddr();
//            log.info("用户IP：{} 执行了{},类:{},方法名：{},参数:{}", ipAddress, operation, targetName, methodName, paramsBuf);
//            log.info("异常信息:{}", e.getMessage());
//        } catch (Exception ex) {
//            log.error("异常信息:{}", ex.getMessage());
//        }
    }

    // 处理异常信息  toAbnormalInfo
    public void toAbnormalInfo(JoinPoint joinPoint, Throwable e) {
        log.info("============================ 记录日志或者异常 =============================");
        try {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class<?> targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String operation = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class<?>[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        operation = method.getAnnotation(UserOptLogger.class).operation();
                        break;
                    }
                }
            }
            StringBuilder paramsBuf = new StringBuilder();
            for (Object arg : arguments) {
                paramsBuf.append(arg);
                paramsBuf.append("&");
            }
            // *========控制台输出=========*//
            String ipAddress = IpUtils.getIpAddr();
            log.info("用户IP：{} 执行了{},类:{},方法名：{},参数:{}", ipAddress, operation, targetName, methodName, paramsBuf);
            if(e != null ){
                log.info("异常信息:{}", e.getMessage());
            }
        } catch (Exception ex) {
            log.error("异常信息:{}", ex.getMessage());
        }


    }


}

